package fileshare.network;

import java.io.*;
import java.net.*; 
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random; 
import java.util.Vector;

import fileshare.datastructure.Msg;
import fileshare.datastructure.UniContainer;
import fileshare.fileprocessing.log;
public class taskthread implements Runnable
{
	
	private boolean isend;
	private boolean isreceive;
	
	private boolean GetBitmap=false;
	private boolean ACK=false;
	private boolean SendAck=false;
	private boolean SendSignal=false;
	private  boolean first2=true;
public static Socket threadsock;
	Socket assitantsock;
	DataInputStream getMessageStream = null;
	private   DataInputStream in =null;
	private  DataOutputStream out=null;
	public  String filepath="CEN5501C//";//the filepath underCEN5501C
	private  String filepathcomplete="CEN5501C\\cmn.txt";
	private volatile boolean hdsk=false;
	private volatile int targetpeerindex=-1;
	private  volatile int targetpeerid;
	private  boolean itcome=false;
	private  boolean filecomplete=false;
	private  boolean firstrun=true;
	private  boolean firstbitmap=true;
	private  int remain=(int)peerProcess.remainsize;
	private  int piecenumber=(int)peerProcess.piecenumber;
private  int piecesize=(int)peerProcess.piecesize;
	private peerProcess pr=null;
	private  Random r = new Random(); 
	private  byte[]newbyte;
	private  String send_msg="CEN5501C2008SPRING0000000000"+peerProcess.str_peerid;//initial value bitfield
	private  int []Tbitmap;//the bitmap for this thread after receive the piece update this and the 
	
	private  int selfpeerid=peerProcess.self_peerid;
	private  int selfindex=peerProcess.self_index;

	

	private  DataInputStream fis = null;
	private  DataOutputStream fileOut=null;
	private  DataOutputStream ps = null;//new DataOutputStream(threadsock.getOutputStream());
	//main process bitmap
	String ip=null;
	int port =0;
	//a container for all the nuniversal variable shared by taskthread and secondthread 
	public UniContainer U1=null;
	public UniContainer U=null;
	public taskthread(String ip,int po,peerProcess p1)throws Exception
	{
		pr=p1;
		U1=new UniContainer();
		
	this.ip=ip;
	this.port=po;
	this.CreateConnection();
	SecondTaskThread ta=new SecondTaskThread(threadsock.getLocalPort()+1,U1);
	Thread startit=new Thread(ta);
	startit.start();
	
	isend=true;
	this.assginsocket(isend);
	}                 
	public taskthread(Socket s,peerProcess p1)throws Exception
	{
		pr=p1;
		U1=new UniContainer();//initialize the unicontainer
		threadsock=s;
		String peer2hostname=s.getInetAddress().getHostName();
		int peer2port=s.getPort();//get the peer2's portnumber
		log.writelog("the peer2hostnameis"+peer2hostname);
		log.writelog("the peer2hostport"+peer2port);
		SecondTaskThread ta=new SecondTaskThread(peer2hostname,peer2port+1,U1);
		Thread startit=new Thread(ta);
		startit.start();
		isend=false;
		this.assginsocket(isend);
		
	}
	public void run()// there are 2 sockes here
	{
		
		Tbitmap=new int[(int)peerProcess.piecenumber];
		for(int i=0;i<(int)peerProcess.piecenumber;i++)
		{
			Tbitmap[i]=0;
		}
		//log.writelog("inside run1 of taskthread ");
		

	
		try{
			if(!isend)// if plays as the server
			{	while(true)//712
	{
			//log.writelog("I am server now");
		
			if(!U1.gethdsk())
			{readhandshake();continue;}
		
	//	log.writelog("inside big while of receiver taskthread");
		//RecvMsg();
		if(targetpeerindex>0)
		{
			//System.out.println("debug"+(peerProcess.checksendsig(targetpeerindex)&&peerProcess.ifallpeerfi()));
		if(peerProcess.checksendsig(targetpeerindex)&&peerProcess.ifallpeerfi())
		{
			cleansocket();
			System.exit(0);
	break;
		}
		}
		RecvMsg();
	}
			}
			else 
			{
			
				while((!SendSignal||!peerProcess.ifallpeerfi()))
				{
					//log.writelog("target peer haha"+targetpeerindex);
					U=new UniContainer();//initialize the unicontainer
						//log.writelog("inside taskthread big while sender sendertaskthread");
						
					//if this is the first time to run
						
						if(firstrun)
							{Makehandshake();firstrun=false;}
						if(!U1.gethdsk())//if the handshake msg of the target not yet received
							{continue;}
						else if(firstbitmap)
						{
							targetpeerid=U1.gettargetid();
							targetpeerindex=U1.gettargetindex();
							makebitfield();
							firstbitmap=false;
						}
						
					Msgprocess();
					if(!peerProcess.checkpeerstat(targetpeerindex))
					{
					int targetstatus=peerProcess.prq.checkChoke(this.targetpeerindex);
					if(targetstatus==1)
						makemsg(1,1,0,0);//notify the target is unchoked
						else
							if(targetstatus==0)
					
								makemsg(1,0,0,0);
					}
					
					peerProcess.completeflag=peerProcess.mapvector.iscomplete(peerProcess.self_index);
					filecomplete=peerProcess.completeflag;
					// file complete now and we have not yet told other guys
					if(filecomplete&&!SendSignal)
					{peerProcess.changecompeer(peerProcess.self_index);
					notifyComplete();
					SendSignal=true;
					peerProcess.changesendsig(targetpeerindex);
					U1.chgsig(true);//to let the receiving thread know about this
					}
					//sending have when receive new pieces
					if(peerProcess.comflag!=1&&!peerProcess.checkpeerstat(targetpeerindex))//error1
					{
					int newbit=Imapcheck();
					if(newbit!=-1)
					{
						makemsg(5,4,newbit,4);}
					}//error1
					//log.writelog("inside taskthread big whilerun5");
					//RecvMsg();
					//Imapcheck();
					Date currentTime = new Date();    
					  SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");    
					  String dateString = formatter.format(currentTime); 
					if(!(!peerProcess.ifallpeerfi()||!SendSignal))
					{
						/*log.writelog("empty sender");
						Msg get=null;
							while((get=U1.getFromSender())!=null)
							{
								SendMsg(get);
							}*/
						cleansocket();
						
						log.writelog(dateString+"while end for target peer"+targetpeerindex);
						break;
						}
					
				}
				
			}
			}catch(Exception e){e.printStackTrace();log.getExceptionTrace(e);log.writelog("ping pong game err");}
		log.writelog("taskthread at big while");
		log.writelog("run end for target peer"+targetpeerindex);
		System.exit(0);
		}
		//if it is a receiver, then threadsock is recever and assitant is sender
		

	//sending
	private  void SendMsg(Msg ms)throws Exception
	{
		try{
		byte[]msg=ms.msg;
		int length=ms.msglength;
		log.writelog("the length of sent message is"+length);
		out.write(msg, 0, length); 
	
		out.flush();
		String m=new String(msg);
		}catch (Exception e){e.printStackTrace();log.getExceptionTrace(e);}
	//	log.writelog("taskthread dirty sender"+m+"to peer"+targetpeerindex);
		
	}
	private  Msg readMsgQue()
	{
		while(true)
		{
			int newbit=Imapcheck();//get back the new piece info of received
			if(newbit!=-1)
			{makemsg(5,4,newbit,4);}//make a have msg 
			Msg getmsg=U1.getFromRecever();
			if(getmsg==null)
				continue;    //here there might be problem leading to deadlock
			return getmsg;
			
			
		}
	}
	
	//receving
	private  void RecvMsg()throws IOException
	{
	checkInput();	
	}
	private  int Imapcheck()//see the new change of bitmap
	{
		for(int i=0;i<(int)peerProcess.piecenumber;i++)
		{
			if(peerProcess.bitmap[i]!=Tbitmap[i])
				{Tbitmap[i]=peerProcess.bitmap[i];return i;}
			
		}
		return -1;
		
	}
	private  void Msgprocess()throws Exception// need to update 
	{
		Msg msg=null;
		while((msg=U1.getFromRecever())!=null)
		try{
		
		if(msg==null)
			{ log.writelog("no mssage can be received in the receve box taskthread");return;}  
		
		byte buf[]=msg.msg;
		int type=(buf[0]&0xff);
		//log.writelog("type is "+type);
		int length=msg.msglength;
		switch(type)
		{
		
		case 0: {log.writelog("taskthread receive choke");//choke do nothing
		peerProcess.unchokeme[targetpeerindex]=0;
		String content="is choked by peer "+targetpeerindex;
		log.write2log(content);
		}break;
		case 1: {//it is a unchoke,get this msg my next sending will be a piece request
			makerequest();
			peerProcess.unchokeme[targetpeerindex]=1;
			String content="is unchoked by peer "+targetpeerindex;
			log.write2log(content);
		} break;
		case 2: {putinterest(targetpeerindex);
		String content="received the interested message from peer"+this.targetpeerindex;
		log.write2log(content);
		}break;//
		case 3: {//log.writelog("second taskthread receive not interested in me"+targetpeerindex);
		peerProcess.prq.rminterest(targetpeerindex);
		String content="received the [not interested] message from peer"+this.targetpeerindex;
		log.write2log(content);
		
		
		}  break;
		case 4:{                              //receive a have
			//read the piece index out
			int pieceindex=readindex(buf);
			String content="received the have message from "+targetpeerindex+"for the piece["+pieceindex+"]";
			log.write2log(content);
			int still=peerProcess.stillno(pieceindex);
			if(still!=1)
			{makemsg(1,3,0,0);//no, i have no interest
		log.writelog(" taskthread receive have boring piece"+pieceindex);}
		else
			{
			makemsg(1,2,0,0);
			peerProcess.mapvector.changebitmap(targetpeerindex,pieceindex);
			log.writelog("taskthread receive have interesting piece"+pieceindex);
			}//yes i have interest
			
		      }
		break;
		
		case 5:  //receive a bitfield after handshake
		{
			//byte[]bm=new byte[(int)peer.piecenumber];
			//parse the bitmap 
			GetBitmap=true;
			int numberofp=(int)peerProcess.piecenumber;
			int len=numberofp/8;
			int remain;
			if((remain=numberofp%8)>0)
				len=len+1;
			int []mp=new int[(int)peerProcess.piecenumber];
			int begin=0;
		
			for(int i=1;i<len+1;i++)
			{
				
				
				//byte c=buf[i];
				int kid=(int)(buf[i]&0xff);
				String child=Integer.toBinaryString(kid);
				int le = child.length();
				if(i<len)
		    	for (int m=0;m<8-le;m++)
		    	{
		    		child ="0"+child;
		    	}
				if(i==len)//the last piece
					{if(remain==0)
					{
						for (int m=0;m<8-le;m++)
				    	{
				    		child ="0"+child;
				    	}
					}
					else
					{
						if(le<remain)
						{
							for(int jj=0;jj<remain-le;jj++)
								child="0"+child;
							
						}
					}
					
					}
						
				for(int v=0;v<8&&begin<numberofp;v++,begin++)
				{
					String eee="";
					char e=child.charAt(v);
					
					eee=eee+e;
					mp[begin]=Integer.parseInt(eee);
				}
				
			}
			
			//put the target peer's bitmap int the map vector
			peerProcess.mapvector.bitmapadd(mp, targetpeerindex);
			
			boolean intrpiece=readbitfield(targetpeerindex);
			if(intrpiece)
			{makemsg(1,2,0,0);//i have interested in you
		log.writelog("second taskthread receive interesting bit field"+targetpeerindex);}
			else
		log.writelog("second taskthread receive boring bit field"+targetpeerindex);
			
		}
		break;
		case 6://receive a request for piece choke
		{
			int plength;
			int pieceindex=readindex(buf);
			//change 7.16
			if(pieceindex==-(U1.gettargetindex()))//the target peer tells me he is finished
			{
				String content="" +"taskthread receive sign for completement from"+targetpeerindex;
				log.write3log(content);
				peerProcess.changecompeer(U1.gettargetindex());
				return;
			/*	if(!SendAck)
				{
				String content="" +"taskthread receive sign for completement from"+targetpeerindex;
				log.write3log(content);
				peer.changecompeer(U1.gettargetindex());
				//sendback acknowledgement
				/*makesignal(5,6,-(targetpeerindex),4);
				Msg singnal=U.getFromSender();
				SendMsg(singnal);
				SendAck=true;
				return;
				}
				else
					return;*/
			}
			/*if(pieceindex==-(peer.self_index))//This is the ack message
			{
				String content ="" +"taskthread receive ACK from"+targetpeerindex;
				log.write3log(content);
				ACK=true;
				return;
			}*/
			
			boolean chok=checkwhetherchoke(targetpeerindex);//see whether it is choke
			if(chok)
				{makemsg(1,0,0,0);//tell the peer that he is choked and do not send him piec
			log.writelog("" +"taskthread receive questfor piece but choked"+targetpeerindex);}

			else
				{
				
				if(pieceindex!=(int)peerProcess.piecenumber-1||(int)peerProcess.remainsize==0)
					{plength=(int)peerProcess.piecesize+5;}
				else
					plength=(int)peerProcess.remainsize+5;
				
			
				makepiece(plength,7,pieceindex,4);
				log.writelog("taskthread receive questfor piece ok"+this.targetpeerindex+"for piece"+pieceindex+"piecelength"+plength);
				}//ok send him piece
		}
		break;
		case 7://receive a piece
		{
			int pieceindex=readindex(buf);
			receivepiece(pieceindex,length,buf);
			updateselfbitmap(pieceindex);
			for(int i=1;i<7&&i!=peerProcess.self_index;i++)
			{
			int wethint=peerProcess.mapvector.searchinterest(peerProcess.self_index, i);
			if(wethint==-1)
				peerProcess.prq.rminterest(i);
			
			if(wethint==-2&&first2==true)
			{
				//log.writelog("sending completement sign to peer"+targetpeerindex);
				peerProcess.completeflag=true;
				peerProcess.mapvector.changefileflag();
				first2=false;
				peerProcess.changecompeer(peerProcess.self_index);
				//makerequest();
				return;
			}
			if(wethint!=-1&&i==targetpeerindex&&peerProcess.unchokeme[targetpeerindex]==1)//newchange
			{
				
				makerequest();
			}
			//checkneighbourbitmap();//check the neighbor's bitmap if interested say it,if
			//some neighbor doesn't have any,say no
			}
			
			
		}
		break;
		
		
				
		}
	}catch(Exception e){e.printStackTrace();log.getExceptionTrace(e);}
		
		}
		
//make handshake;
	private  void Makehandshake()throws Exception
	{
		out.writeUTF(send_msg);
		
		out.flush();
				log.writelog("sending handshake to the target peer");
		
	}
	/*private  void Makehandshake()throws Exception
	{
		String handsh=send_msg;
		byte[]msg=new byte[32];
		byte[]handshake=new byte[28];
		int k=1234567;
		byte []head=intToByte(k);
	
		for(int i=0;i<4;i++)
			msg[i]=head[i];
		handshake=handsh.getBytes();
		for(int i=4,j=0;i<32;i++,j++)
		{
			msg[i]=handshake[j];
		}
		sendmsgque.add(msg, 32);//
		
		//   sendmsgque.addstring(handsh,-32);//7.3

		log.writelog("adding handshake into the sendbox");
		
	}*/
	
//read index infomation from the received msg including have,request,
	private  int readindex(byte[]buf)
	{
		byte []nmsg=new byte[4];
		for(int i=1,j=0;i<5;i++,j++)
		{
			nmsg[j]=buf[i];
		}
		int ind=bytesToInt(nmsg);
		return ind;
	}
	//read handshake msg
	private  void readhandshake(byte [] buf)throws Exception
	{	byte[]pd=new byte[33];
		for(int i=0,j=0;i<33;i++,j++)
			pd[j]=buf[j];
		//int jj=bytesToInt(pd);
		String targetp=new String(pd);
		String num="";
		for(int i=29;i<33;i++)
		{
			num=num+targetp.charAt(i);
		}
		log.writelog("targetpeerid"+num);
		
		targetpeerid=Integer.parseInt(num);
		targetpeerindex=peerProcess.peerip_container.id2index(targetpeerid);
		/*String content="is connected from peer"+taskthread.targetpeerid;
		log.write2log(content);*/
		log.writelog("receive handshake message from targetpeerid"+targetpeerid);
		
		
	}
	public  void readhandshake()throws Exception
	{	
		String handshake=in.readUTF();
		String num=handshake.substring(28);
		targetpeerid=Integer.parseInt(num);
		targetpeerindex=peerProcess.peerip_container.id2index(targetpeerid);
		U1.puttargetid(targetpeerid);
		U1.puttargetindex(targetpeerindex);
		String content="is connected from peer"+targetpeerid;
		log.write2log(content);
		hdsk=true;
		U1.chghdsk(hdsk);
		//log.writelog("second workthread receive handshake message from targetpeerid"+targetpeerid);
		//log.writelog("receive handshake message from targetpeerid"+targetpeerid);
		
		
	}
	/*private  int checkbitmap()
	{
		int index;
		
		retrun index;
	}*/
	private  void putinterest(int peerid)
	{
		//log.writelog("taskthread receive interested in me"+U1.gettargetindex());
		
		//peer.interested[peerid]=1;
		peerProcess.prq.addinterest(peerid);//put this loving me peer into the peer relation manager preque.java
		
	}
	private  void receivepiece(int pieceindex,int length,byte[]buf)throws Exception
	{
		//String piecedir="CEN5501C\\"+peer.realfilename+"."+pieceindex;//cen
String piecedir=peerProcess.dirname+"//"+peerProcess.realfilename + "_" +pieceindex+peerProcess.ext;
		String content="has downloaded the piece_"+pieceindex+" from peer"+targetpeerindex;
		log.write2log(content);
		// read from the the 5th bit until end
		//if this is the last piece of the file
		if(pieceindex==piecenumber-1&&peerProcess.remainsize!=0)
		{
			//though when sent here the data payload is a complete piece size
			//however the last serveral bits is invalid
			byte[]recbuf=new byte[(int)peerProcess.remainsize];//the buf should be as large as the remain perhaps wrong
			for(int i=5,j=0;i<(int)peerProcess.remainsize+5;i++,j++)
			{
				recbuf[j]=buf[i];
			}
			//log.writelog("checking piecereceive"+new String(recbuf));
			DataOutputStream fileOut = new DataOutputStream(new BufferedOutputStream(
					 new BufferedOutputStream(new FileOutputStream(piecedir))));
			//String putin=new String(recbuf);
			//fileOut.writeBytes(putin);
			fileOut.write(recbuf,0,(int)peerProcess.remainsize);
			fileOut.flush();
			fileOut.close();
			//log.writelog("taskthread receive last piece from"+targetpeerindex);
			
		}
		else
			{
				//though when sent here the data payload is a complete piece size
				//however the last serveral bits is invalid
				byte[]recbuf=new byte[piecesize];//the buf should be as large as the remain perhaps wrong
				for(int i=5,j=0;i<piecesize+5;i++,j++)
				{
					recbuf[j]=buf[i];
				}
				//log.writelog("checking piecereceive"+new String(recbuf));
				DataOutputStream fileOut = new DataOutputStream(new BufferedOutputStream(
						 new BufferedOutputStream(new FileOutputStream(piecedir))));
				

				//String putin=new String(recbuf);
				//fileOut.writeBytes(putin);	
				fileOut.write(recbuf,0,piecesize);
				fileOut.flush();
				fileOut.close();
			
			
				String loge="second taskthread receive  piece from"+targetpeerindex;
				log.write2log(loge);
				
		
	}
	}
	
	/**
	 * 
	 * @param length the length without head
	 * @param type
	 * @param piindex the piece wonna send
	 * @param indexlen 4
	 */
	private  void makepiece(int length,int type,int piindex,int indexlen)throws Exception
	{
		DataInputStream fis =null;
		
		fis = new DataInputStream(new BufferedInputStream(
				new FileInputStream(peerProcess.dirname+"//"+peerProcess.realfilename + "_" +piindex+peerProcess.ext)));
		int totalsize=(int)peerProcess.piecesize;
		int actread=0;
		byte[] buf;
		byte[]buf2;
		if(piindex!=peerProcess.piecenumber-1)
		{buf = new byte[totalsize]; actread=totalsize; }
		else
			{buf=new byte[(int)peerProcess.remainsize];
			
			actread=(int)peerProcess.remainsize;}
		buf2 = new byte[actread];
		int len=0;
		int read;
		while((read=fis.read(buf))!=-1)
		{
			
			if(len+read<=actread)
			{
			for(int i=len;i<read+len;i++)
				buf2[i]=buf[i];
			len=len+read;
			
			}
		}		
		type=7;
		indexlen=4;
		int totallength=5+indexlen+actread;//4+1+4+piecesize
		byte []newbyte=new byte[totallength];
		byte []msglength=new byte[4];
		byte []msgtype=new byte[1];
		byte []pieceindex=new byte[4];
		msglength=intToByte(length);
		//msgtype=intToByte(type);
		byte tp=(byte)(7&0xff);
		pieceindex=intToByte(piindex);
		for(int i=0;i<4;i++)
		{
			newbyte[i]=msglength[i];
		}
		newbyte[4]=tp;
		
		for(int i=5,j=0;i<9;i++,j++)
		{
			newbyte[i]=pieceindex[j];
		}
		for(int p=9,k=0;p<totallength;p++,k++)
		{
			newbyte[p]=buf2[k];//newchange
		}
		SendOutMessage(newbyte, totalsize+9);
		
		
			
	
		}
		
		
		
	//make final signal message
	private  void makesignal(int length,int type,int index,int indexlen)
	{
		int totallength=5+indexlen;
		byte []newbyte=new byte[totallength];
		byte []msglength=new byte[4];
		byte []msgtype=new byte[1];
		byte []pieceindex=new byte[4];
		msglength=intToByte(length);
		//msgtype=intToByte(type);
		byte tp=(byte)(type&0xff);
		pieceindex=intToByte(index);
		for(int i=0;i<4;i++)
		{
			newbyte[i]=msglength[i];
		}
		newbyte[4]=tp;
		
		for(int i=5,j=0;i<totallength;i++,j++)
		{
			newbyte[i]=pieceindex[j];
		}
		U.addToSender(newbyte, totallength);
		
		
	}

	
	private  void makebitfield()
	{
		
		int numberofp=(int)peerProcess.piecenumber;
		int length=numberofp/8;
		int remain;
		if((remain=numberofp%8)>0)
			length=length+1;
		if (remain==0)
			remain=8;
		int[]nbn=peerProcess.bitmap;
		String bits="";
		int begin=0;
		int end=8;
		byte []bitfi=new byte[length];
		for(int j=0;j<length-1;j++)
		{
			String every8="";
		for(int i=begin;i<end;i++)
		{
			every8=every8+nbn[i];
			
		}
		int value=Integer.parseInt(every8,2);
		bitfi[j]=(byte)(value&0xff);
		begin=begin+8;
		end=end+8;
		}
		String rem="";
		for(int i=0,j=begin;i<remain;i++,j++)
		{
			rem=rem+nbn[j];
		}
		int value2=Integer.parseInt(rem,2);
		bitfi[length-1]=(byte)(value2&0xff);
		int msglength=length+1;
		byte header[]=new byte[4];
		header=intToByte(msglength);
		byte typ=(byte)(5&0xff);
		byte msgsend[]=new byte[5+length];
		for(int i=0;i<4;i++)
		{
			msgsend[i]=header[i];
		}
		msgsend[4]=typ;
		for(int i=5,j=0;i<5+length;i++,j++)
		{
			msgsend[i]=bitfi[j];
		}
	
		SendOutMessage(msgsend, length+5);
		log.writelog("taskthread send bitfield to"+targetpeerindex);
		
	}
	private  boolean checkwhetherchoke(int peerid)//check whether a certain peer is choke
	{
		boolean choke=peerProcess.whetherchoke(peerid);
		return choke;
		
	}
	private  void updateselfbitmap(int pieceindex)//after receving a have msg do this//newchange
	{
		peerProcess.mapvector.changebitmap(peerProcess.self_index, pieceindex);
		
	}
	private  void updatepeerbitmap(int index,int targetpeernumber)//after receving a have msg do this
	{
		peerProcess.mapvector.changebitmap(targetpeernumber, index);
	}
	/**
	 * 
	 * @param peerindex
	 * @return
	 */
	private  boolean readbitfield(int peerindex)
	{
		int interested;
		interested=peerProcess.mapvector.searchinterest(selfindex, peerindex);
		if(interested!=-1&&interested!=-2)
		
		return true;
		
		else return false;
		
	}
	private  void makerequest()
	{
		// create a request msg
		for(int i=0;i<5;i++)
		{
		int index=randompiece();
		if(index==-1)
			return;
		if(index==-2)//send special request to target peer to tell I am finished
		{filecomplete=true;return;}//complete do nothing 
		makemsg(5,6,index,4);
		log.writelog("taskthread make request for piece #"+index+"to target"+targetpeerindex);
		if(index!=-2)
		peerProcess.bitreqsta[index]=1;
		}
		}
	//notify the target that it is over with selfindex
	private void notifyComplete()
	{
		log.writelog("download is complete");
		makemsg(5,6,-(peerProcess.self_index),4);
		String content="taskthread send over signal to target"+targetpeerindex;
		try{
		log.write3log(content);
		}catch(Exception e){}
	
	}
	/**
	 * 
	 * @param length the length of the message without the head
	 * @param type
	 * @param index
	 * indexlen 0 or a lot
	 */
	public  void makemsg(int length,int type,int index,int indexlen)
	{
		int totallength=5+indexlen;
		byte []newbyte=new byte[totallength];
		byte []msglength=new byte[4];
		byte []msgtype=new byte[1];
		byte []pieceindex=new byte[4];
		msglength=intToByte(length);
		//msgtype=intToByte(type);
		byte tp=(byte)(type&0xff);
		pieceindex=intToByte(index);
		for(int i=0;i<4;i++)
		{
			newbyte[i]=msglength[i];
		}
		newbyte[4]=tp;
		
		for(int i=5,j=0;i<totallength;i++,j++)
		{
			newbyte[i]=pieceindex[j];
		}
		SendOutMessage(newbyte, totallength);
		
		
	}
	/**
	 * 
	 * @return the desired index which i do not have or -1 means i have all the pieces the target peer has
	 */
	private  int randompiece()
	{
		int choice;
		// choose a random piece from the bitmap which I do not have
		while(true)
		{
			//int choice=r.nextInt((int)peer.piecenumber);  
			//int isrecevied=peer.stillno(choice);
			//get the piece index that i do not have 
			choice =peerProcess.mapvector.searchinterest(peerProcess.self_index, targetpeerindex);
			if(choice==-1)
				break;// not interest
			if (choice!=-1)
				return choice;
			
		}
		
		return choice;//complet flag
	}
	// assign task for these 2 socket,one as recever one as sender,this is based on wether the thread sock socket
	//is created by sending out connection request or not
	private void assginsocket(boolean sender)throws IOException
	{
		if(sender)//if the threadsock socket initialized by a sender peering
			// set threadsock to be sending socket
			
		{		
			out =new DataOutputStream(threadsock.getOutputStream()); 
			//DataInputStream fis = new DataInputStream(new BufferedInputStream(
					//new FileInputStream(filepathcomplete)));
			
			
		}
		else
		{
			 in=new DataInputStream(new BufferedInputStream(
						threadsock.getInputStream())); 
			 
			 
			 
			
		}
	}
	//clean socket
	
	//clean the socket
	private void cleansocket()throws IOException
	{
		try{
		if(isend)//if the threadsock socket initialized by a sender peering
			// set threadsock to be sending socket
			
		{		
			if(out!=null)
			out.close();
			log.writelog("clean out for"+targetpeerindex);
			
		}
		else
		{
			if(in!=null)
			 in.close();
			 log.writelog("clean in for"+targetpeerindex);
			 
			 
			
		}
		}catch(Exception e){e.printStackTrace();}
		finally{
			if(isend)
			out.close();
			else
			in.close();
		}
	}
	//MESSAGE SENDER
	private void SendOutMessage(byte [] b,int len)
	{
		UniContainer UNI=new UniContainer();
		UNI.addToSender(b, len);
		Msg product=UNI.getFromSender();
		try{
		SendMsg(product);
		}catch(Exception e){e.printStackTrace();log.getExceptionTrace(e);}
	}
	
	private  void checkInput()throws IOException
	{
		
		//log.writelog("inside checkinput");
		try{
		byte head[]=new byte[4];
if(in==null)
			return;
		for(int i=0;i<4;i++)
		{
			head[i]=in.readByte();
		}
		
		String w=new String(head);
		int length=bytesToInt(head);
	//	log.writelog(w);
		
			byte msg[]=new byte[length];
			for(int i=0;i<length;i++)
			{
				msg[i]=in.readByte();
			}
			U1.addToRecever(msg, length);
		}catch(Exception e){
			e.printStackTrace();
			if(peerProcess.checksendsig(targetpeerindex)&&peerProcess.ifallpeerfi())
				{cleansocket();return;}
		}
		
	}
	
	public  byte[] intToByte(int i) {
	    byte[] abyte0 = new byte[4];
	    abyte0[0] = (byte) (0xff & i);
	    abyte0[1] = (byte) ((0xff00 & i) >> 8);
	    abyte0[2] = (byte) ((0xff0000 & i) >> 16);
	    abyte0[3] = (byte) ((0xff000000 & i) >> 24);
	    return abyte0;
	}
	public   int bytesToInt(byte[] bytes) {
	    int addr = bytes[0] & 0xFF;
	    addr |= ((bytes[1] << 8) & 0xFF00);
	    addr |= ((bytes[2] << 16) & 0xFF0000);
	    addr |= ((bytes[3] << 24) & 0xFF000000);
	    return addr;
	}
private int getconnectingpeerid()
{
	

	String tip=threadsock.getInetAddress().getHostName();
	int pt=threadsock.getPort();
	String intrtargetpeerid=peerProcess.peerip_container.getipinfobyhostnameport(tip).peeridinfo;
	int targetpeerid=Integer.parseInt(intrtargetpeerid);
	return targetpeerid;
}

	

public void CreateConnection() //send connection to target peer
{
	try {
		while(true)
		{
			Thread.sleep(100);
			//InetAddress ddress = InetAddress.getByName(ip);
		threadsock = new Socket(ip, port); 
			//threadsock = new Socket("192.168.1.3", 6008); 
		log.writelog("connecting to ip"+ip+"port"+port);
		if (threadsock!=null);
		break;
		}
	
	} catch (Exception e) {
	e.printStackTrace(); log.getExceptionTrace(e);
	if (threadsock != null)
		try {
		threadsock.close(); 
		}catch (Exception g){
			g.printStackTrace();log.getExceptionTrace(g);
		}
	}
}
public byte[] Convert(String temp){     
    byte[] b=new byte[4];
    int i,j,k;
    for(i=0,j=0,k=0;i<temp.length();i++){
         if(temp.charAt(i)=='.'){
            b[k++]=(byte)Integer.parseInt(temp.substring(j,i));
            j=i+1;
         }
         if(k==3) break;
        } 
        b[k]=(byte)Integer.parseInt(temp.substring(j,temp.length()));
        return b;
    }

public void CreateassitantConnection() //send another connection to target peer
{
	try {
		while(true)
		{
			
		assitantsock = new Socket(ip, port); //to the new socket in the target peer's thread
		if (assitantsock!=null);
		break;
		}
	
	} catch (Exception e) {log.getExceptionTrace(e);
	e.printStackTrace();log.getExceptionTrace(e); 
	if (assitantsock != null)
		try {
			assitantsock.close(); 
		}catch (Exception g){
			g.printStackTrace();
			log.getExceptionTrace(g);
		}
	}
}
public void ReceiveassitantConnection() // establish another listener which is binded to port+10 to wait for second connection
										//and then establish the second passive socket 
{
	try{
		Socket s = null;
		ServerSocket ss = new ServerSocket(port+11);
		//incomming connections
		while(true)//here this function is used to listen to outsider connection
		{
			log.writelog("waiting for client2");
			Thread.sleep(100);
			try{
				assitantsock=ss.accept();
			}catch(Exception e){log.getExceptionTrace(e);}
			if(s!=null)
			{
			log.writelog("new assistant thread is ok");
			}
		}
		}catch(Exception e){log.getExceptionTrace(e);log.writelog("ServerSocket wrong");}
}


public  DataInputStream getMessageStream() 
{
	try {
	getMessageStream = new DataInputStream(new BufferedInputStream(
			threadsock.getInputStream())); 
	return getMessageStream; 
	} catch (Exception e) {
		log.getExceptionTrace(e);
	e.printStackTrace();log.getExceptionTrace(e); 
	if (getMessageStream != null)
		try{
	getMessageStream.close(); 
		}catch (Exception h) {
			h.printStackTrace();log.getExceptionTrace(h); }
	 
	} 
	finally
		{
		}
	if(getMessageStream==null)
		return null;
	else return getMessageStream;
}
}
